package cn.dyp.com.automaticcontrolserver.serial;

import java.util.ArrayList;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;


import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;

import cn.dyp.com.automaticcontrolserver.bean.Controller;
import cn.dyp.com.automaticcontrolserver.bean.Sensor;
import cn.dyp.com.automaticcontrolserver.ServerApp;
import cn.dyp.com.automaticcontrolserver.serialport_api.ZigbeeAdapter;

/**
 * 串口读写service类, 作为service在后台运行
 * 
 * @author asus
 *
 */
public class SerialportService extends Service {
	private ServerApp mApp;
	public static boolean ifSimulate = false;// 是否模拟
	private static ArrayList<Sensor> mSensorList = new ArrayList<Sensor>(); // 传感器数组
	private static ArrayList<Controller> mControllerList = new ArrayList<Controller>(); // 控制器数组
	private ZigbeeAdapter mAdapter;
	private Timer mTimer;// 定时器，每一秒钟取一次传感器数据
	// 广播接收器，用来接收来自Net server的命令
	private SendToSerialportServiceBroadcast mBroadcast;
	public static Date mStartTime;// 服务开始时间

	private boolean isAuto = false;

	@Override
	public IBinder onBind(Intent intent) {
		return null;
	}

	@Override
	public void onStart(Intent intent, int startId) {
		try {
			mApp = (ServerApp) getApplication();
			initData();

			// 创建 ZigbeeAdapter对象
			mAdapter = new ZigbeeAdapter(mHandler);
			// 调用接口，初始化外接Zigbee串口模块
			mAdapter.initSerial("/dev/ttySAC0", 115200);
			// 调用外部接口，对外部Zigbee模块执行协议握手
			mAdapter.devHands();
		} catch (Exception e) {
			e.printStackTrace();
		}
		setTimer();
	}

	/**
	 * 设置计时器
	 * 
	 */
	private void setTimer() {
		mTimer = new Timer();
		mTimer.schedule(new CO2SensorTask(), 1000, 1000);
	}

	/**
	 * 初始化传感器数组
	 * 
	 */
	private void initData() {
		mSensorList.clear();
		mSensorList.add(new Sensor(Sensor.PM25_SENSOR, 0x00));
		mSensorList.add(new Sensor(Sensor.CO2_SENSOR, 0x00));
		mSensorList.add(new Sensor(Sensor.AIR_TMPER_SENSOR, 0x00));
		mSensorList.add(new Sensor(Sensor.AIR_HUMID_SENSOR, 0x01));
		mSensorList.add(new Sensor(Sensor.SOIL_TMPER_SENSOR, 0x00));
		mSensorList.add(new Sensor(Sensor.SOIL_HUMID_SENSOR, 0x01));
		mSensorList.add(new Sensor(Sensor.LIGHT_SENSOR, 0x00));

		// 初始化控制器数组
		mControllerList.clear();
		mControllerList
				.add(new Controller(Controller.WATER_PUMP_CONTORL, 0x00));
		mControllerList.add(new Controller(Controller.BLOWER_CONTORL, 0x01));
		mControllerList.add(new Controller(Controller.BUZZER_CONTORL, 0x03));
		mControllerList.add(new Controller(Controller.ROADLAMP_CONTORL, 0x02));

	}

	@Override
	public void onCreate() {
		super.onCreate();
		regiesterReceiver();
	}

	/**
	 * 在创建该服务时，要立刻注册相关广播接收器
	 * 
	 */
	private void regiesterReceiver() {
		mBroadcast = new SendToSerialportServiceBroadcast();
		IntentFilter intentFilter = new IntentFilter();
		intentFilter
				.addAction("com.lenovo.agriculture.server.broadcat.senttoserialport");
		registerReceiver(mBroadcast, intentFilter);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		// 释放定时器资源
		if (mTimer != null) {
			mTimer.cancel();
		}
		// 释放串口资源
		mAdapter.closeSerial();
		if (mBroadcast != null) {
			unregisterReceiver(mBroadcast);
		}
	}

	/**
	 * 处理来自外部设备上报的传感数据
	 * 
	 * @author asus
	 *
	 */
	public Handler mHandler = new Handler(new Handler.Callback() {

		@Override
		public boolean handleMessage(Message msg) {
			switch (msg.what) {
			case 1:
				getAddress(msg);
				break;

			case 2:
				submitData(msg);
				break;
			}
			return false;
		}
	});

	/**
	 * 根据控制器名称打开相应的控制器
	 * 
	 * @param name
	 *            控制器名称
	 */
	public void openControllerByName(String name) {
		Controller controller = Controller.getControllerByName(mControllerList,
				name); // 找到控制器
		if (controller != null && controller.getAddr() != null) // 并且控制器的地址不能为空
		{
			mAdapter.controlAct(controller.getAddr(), controller.getSubDev(),
					0x31);
		}
	}

	/**
	 * 根据控制器名称关闭相应的控制器
	 * 
	 * @param name
	 *            控制器名称
	 */
	public void closeControllerByName(String name) {
		Controller controller = Controller.getControllerByName(mControllerList,
				name); // 找到控制器
		if (controller != null && controller.getAddr() != null) // 并且控制器的地址不能为空
		{
			mAdapter.controlAct(controller.getAddr(), controller.getSubDev(),
					0x30);
		}
	}

	/**
	 * 线程等待
	 * 
	 */
	public void threadWait() {
		try {
			Thread.sleep(500);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/**
	 * 处理pm2.5, Co2和灯光传感器的地址
	 * 
	 * @param addr
	 *            传感器的地址
	 * @param nameStr
	 *            传感器名字
	 */
	private void handlePm2Co2(byte[] addr, String nameStr) {
		if (nameStr.equals(Sensor.PM25_SENSOR)
				|| nameStr.equals(Sensor.CO2_SENSOR)
				|| nameStr.equals(Sensor.LIGHT_SENSOR)) {
			// 根据传感器名称设置传感器地址
			Sensor sensor = Sensor.getSensorByName(mSensorList, nameStr);
			if (sensor != null) {
				sensor.setAddr(addr);
			}
		}
	}

	/**
	 * 处理空气温湿度传感器的地址,它们共用一个地址
	 * 
	 * @param addr
	 *            传感器地址
	 * @param nameStr
	 *            传感器名字
	 */
	private void handleAir(byte[] addr, String nameStr) {
		if (nameStr.equals(Sensor.AIR_TMPER_SENSOR)) {
			Sensor sensor = Sensor.getSensorByName(mSensorList, nameStr);
			if (sensor != null) {
				sensor.setAddr(addr);
			}
			sensor = Sensor.getSensorByName(mSensorList,
					Sensor.AIR_HUMID_SENSOR);
			if (sensor != null) {
				sensor.setAddr(addr);
			}
		}
	}

	/**
	 * 处理土壤温湿度传感器的地址,它们共用一个地址
	 * 
	 * @param addr
	 *            传感器地址
	 * @param nameStr
	 *            传感器名字
	 */
	private void handleSoil(byte[] addr, String nameStr) {
		if (nameStr.equals(Sensor.SOIL_TMPER_SENSOR)) {
			Sensor sensor = Sensor.getSensorByName(mSensorList, nameStr);
			if (sensor != null) {
				sensor.setAddr(addr);
			}
			sensor = Sensor.getSensorByName(mSensorList,
					Sensor.SOIL_HUMID_SENSOR);
			if (sensor != null) {
				sensor.setAddr(addr);
			}
		}
	}

	/**
	 * 处理控制器的地址
	 * 
	 * @param addr
	 *            传感器地址
	 * @param nameStr
	 *            传感器名字
	 */
	private void handleControl(byte[] addr, String nameStr) {
		if (nameStr.equals(Controller.WATER_PUMP_CONTORL)) {
			// 所有的控制器都共用一个地址
			for (Controller controller : mControllerList) {
				controller.setAddr(addr);
				// 获得控制器地址时，先关闭控制器
				mAdapter.controlAct(controller.getAddr(),
						controller.getSubDev(), 0x30);
				threadWait();
			}
		}
	}

	/**
	 * 自动控制逻辑要在服务开启10秒以后再启动
	 * 
	 */
	private void autoControl() {
		if (mStartTime != null && mApp.getControlAuto() > 0) {
			Date now = new Date();
			if (now.getTime() - mStartTime.getTime() > 10000) {
				Sensor pm25 = mSensorList.get(0);// PM2.5浓度传感器
				Sensor co2 = mSensorList.get(1);// CO2浓度传感器
				Sensor airT = mSensorList.get(2);// 空气温度传感器
				Sensor airH = mSensorList.get(3);// 空气湿度传感器
				Sensor soilT = mSensorList.get(4);// 土壤温度传感器
				Sensor soilH = mSensorList.get(5);// 土壤湿度传感器
				Sensor light = mSensorList.get(6);// 光照强度传感器

				Controller waterPump = mControllerList.get(0);// 水泵控制器
				Controller blower = mControllerList.get(1);// 风扇控制器
				Controller buzzer = mControllerList.get(2);// 蜂鸣器控制器
				Controller roadlamp = mControllerList.get(3);// 路灯控制器
				controlBuzzer(pm25, co2, airT, airH, soilT, soilH, light,
						buzzer);
				controlWaterPump(soilH, waterPump);
				controlBlower(co2, blower);
				controlLight(light, roadlamp);
				isAuto = true;
			}
		}
	}

	/**
	 * 自动控制路灯
	 * 
	 * @param light
	 *            光敏传感器
	 * @param roadlamp
	 *            光照控制器
	 */
	private void controlLight(Sensor light, Controller roadlamp) {
		int isOpenRoadlamp = 0;// 0表示关闭，1表示打开
		// 当光照不足时，开灯
		if (light.getValue() < mApp.getMinLight()) {
			isOpenRoadlamp = 1;
		}
		if (isOpenRoadlamp > 0) {
			openControllerByName(roadlamp.getName());
		} else {
			closeControllerByName(roadlamp.getName());
		}
	}

	/**
	 * 自动控制风扇
	 * 
	 * @param co2
	 *            Co2传感器
	 * @param blower
	 *            水泵控制器
	 */
	private void controlBlower(Sensor co2, Controller blower) {
		int isOpenBlower = 0;// 0表示关闭，1表示打开
		// 不管光照强度如何，如果CO2低于一个阀值就打开风扇换进新风。
		if (co2.getValue() < mApp.getMinCo2()) {
			isOpenBlower = 1;
		}
		if (isOpenBlower > 0) {
			openControllerByName(blower.getName());
		} else {
			closeControllerByName(blower.getName());
		}
	}

	/**
	 * 自动控制水泵
	 * 
	 * @param soilH
	 *            土壤湿度传感器
	 * @param waterPump
	 *            水泵控制器
	 */
	private void controlWaterPump(Sensor soilH, Controller waterPump) {
		int isOpenWaterPump = 0;// 0表示关闭，1表示打开
		// 当土壤湿度低于阀值，打开水泵模拟灌溉。
		if (soilH.getValue() < mApp.getMinEarthHumidity()) {
			isOpenWaterPump = 1;
		}
		if (isOpenWaterPump > 0) {
			openControllerByName(waterPump.getName());
		} else {
			closeControllerByName(waterPump.getName());
		}
	}

	/**
	 * 自动控制蜂鸣器
	 * 
	 * @param pm25
	 *            Pm2.5传感器
	 * @param co2
	 *            Co2传感器
	 * @param airT
	 *            空气温度传感器
	 * @param airH
	 *            空气湿度传感器
	 * @param soilT
	 *            土壤温度传感器
	 * @param soilH
	 *            土壤湿度传感器
	 * @param light
	 *            光敏传感器
	 * @param buzzer
	 *            蜂鸣控制器
	 */
	private void controlBuzzer(Sensor pm25, Sensor co2, Sensor airT,
			Sensor airH, Sensor soilT, Sensor soilH, Sensor light,
			Controller buzzer) {
		int isOpenBuzzer = 0;// 0表示关闭，1表示打开
		// 任选一个传感器都可以跟报警器联动。只需要设置一个报警阀值，大于或者小于阀值都可以报警。
		if (pm25.getValue() > mApp.getMaxPm25()
				|| co2.getValue() > mApp.getMaxCo2()
				|| co2.getValue() < mApp.getMinCo2()
				|| airT.getValue() > mApp.getMaxAirTemperature()
				|| airT.getValue() < mApp.getMinAirTemperature()
				|| airH.getValue() > mApp.getMaxAirHumidity()
				|| airH.getValue() < mApp.getMinAirHumidity()
				|| soilT.getValue() > mApp.getMaxEarthTemperature()
				|| soilT.getValue() < mApp.getMinEarthTemperature()
				|| soilH.getValue() > mApp.getMaxEarthHumidity()
				|| soilH.getValue() < mApp.getMinEarthHumidity()
				|| light.getValue() > mApp.getMaxLight()
				|| light.getValue() < mApp.getMinLight()) {
			isOpenBuzzer = 1;
		}
		if (isOpenBuzzer > 0) {
			openControllerByName(buzzer.getName());
		} else {
			closeControllerByName(buzzer.getName());
		}
	}

	/**
	 * 获取传感器上报数据
	 * 
	 * @param msg
	 *            消息对象
	 */
	private void submitData(Message msg) {
		byte[] addr;
		addr = msg.getData().getByteArray("sensorAddr");// 获取传感器地址
		byte[] dataByte = msg.getData().getByteArray("sensorData");// 获取传感器数据
		int nSub = msg.getData().getInt("SubNum"); // 获取子设备地址
		if (addr != null && dataByte != null) {
			String addrStr = ZigbeeAdapter.Bytes2HexString(addr);
			try {
				float fi = Float.parseFloat(new String(dataByte));// 解析传感器数据
				int value = (int) fi;
				// 获取传感器的值
				for (Sensor sensor : mSensorList) {
					// 先判断地址是否为空
					if (sensor.getAddr() == null) {
						continue;
					}
					// 遍历传感器列表，根据地址找到对应的传感器并设置对应的值
					if (addrStr.equals(ZigbeeAdapter.Bytes2HexString(sensor
							.getAddr())) && sensor.getSubDev() == nSub) {
						sensor.setValue(value);
					}
				}
				// 获取控制器的状态
				for (Controller controller : mControllerList) {
					// 先判断地址是否为空
					if (controller.getAddr() == null) {
						continue;
					}
					// 遍历控制器列表，根据地址找到对应的控制器并设置对应的值
					if (addrStr.equals(ZigbeeAdapter.Bytes2HexString(controller
							.getAddr())) && controller.getSubDev() == nSub) {
						if ((dataByte[0] & 0xff) == 49) {
							controller.setStatus(1);
						} else if ((dataByte[0] & 0xff) == 48) {
							controller.setStatus(0);
						}
					}
				}
			} catch (NumberFormatException e) {
				e.printStackTrace();
			} catch (Exception e) {
				e.printStackTrace();
			}

			autoControl();

			if (isAuto && mApp.getControlAuto() <= 0) {

				for (Controller controller : mControllerList) {
					if (controller.getStatus() == 1) {
						closeControllerByName(controller.getName());
					}
					threadWait();
				}
				isAuto = false;
			}
		}
	}

	/**
	 * 获取外接多个传感模块地址，用于后续对该模块进行数据请求
	 * 
	 * @param msg
	 *            消息对象
	 */
	private void getAddress(Message msg) {
		byte[] addr;
		String nameStr = msg.getData().getString("sensorName"); // 获取传感器名称
		addr = msg.getData().getByteArray("sensorAddr");// 获取传感器地址
		if (addr != null && nameStr != null) {
			mStartTime = new Date();// 记录服务器开始时间
			handlePm2Co2(addr, nameStr);

			handleAir(addr, nameStr);

			handleSoil(addr, nameStr);

			handleControl(addr, nameStr);
		}
	}

	/**
	 * 定时发送消息给外部设备，请求传感数据，包括PM2.5和Co2
	 * 
	 * @author asus
	 *
	 */
	class CO2SensorTask extends TimerTask {
		@Override
		public void run() {
			if (ifSimulate) {
				for (Sensor sensor : mSensorList) {
					sensor.setValue((int) (System.currentTimeMillis() % 99));
				}
			} else {
				// 分别获取当前所有传感器的数据
				for (Sensor sensor : mSensorList) {
					if (sensor.getAddr() == null) {
						continue;
					}
					mAdapter.RequestDeviceData(sensor.getAddr(),
							(byte) sensor.getSubDev());
				}
			}
		}
	};

	/**
	 * 通过传感器的名称获取传感器当前的值
	 * 
	 * @param name
	 *            传感器名称
	 * @return 名称相对传感器的值
	 */
	public static int getSensorValueByName(String name) {
		Sensor sensor = Sensor.getSensorByName(mSensorList, name);
		if (sensor != null) {
			return sensor.getValue();
		} else {
			return -1;
		}
	}

	/**
	 * 通过控制器的名称获取控制器的开关状态
	 * 
	 * @param name
	 *            名称
	 * @return 名称相对的控制器的值
	 */
	public static int getControllerStatusByName(String name) {
		int status = 0;
		Controller controller = Controller.getControllerByName(mControllerList,
				name);
		if (controller != null) {
			status = controller.getStatus();
		}
		return status;
	}

	/**
	 * 控制器控制广播
	 * 
	 * @author asus
	 *
	 */
	class SendToSerialportServiceBroadcast extends BroadcastReceiver {
		@Override
		public void onReceive(Context context, Intent intent) {
			// 用来接收http server或socket server的控制信息
			String message = intent.getStringExtra("message");
			String device = intent.getStringExtra("device");
			int isOpen = intent.getIntExtra("isOpen", -1); // 0 close control,
															// 1open control
			if (message.equals("control")) {
				if (isOpen == 1) {
					openControllerByName(device);
				} else if (isOpen == 0) {
					closeControllerByName(device);
					// 每次给控制器发送命令以后要等待一点时间，便于下位机处理数据
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}
	}
}
